//! 日志系统模块
//! 
//! 提供统一的日志配置、初始化和管理功能

use crate::config::LoggingConfig;
use crate::{Result, Error};
use tracing::Level;
use tracing_subscriber::{
    fmt,
    layer::SubscriberExt,
    util::SubscriberInitExt,
    EnvFilter, Registry,
};
use std::fs::OpenOptions;
use std::path::PathBuf;

/// 日志管理器
pub struct LoggingManager {
    config: LoggingConfig,
}

impl LoggingManager {
    /// 创建新的日志管理器
    pub fn new(config: LoggingConfig) -> Self {
        Self { config }
    }
    
    /// 初始化全局日志系统
    /// 
    /// 根据配置设置日志级别、格式和输出目标
    pub fn init_global_logger(&self) -> Result<()> {
        let env_filter = self.create_env_filter()?;
        
        // 构建订阅器
        match &self.config.file_path {
            Some(file_path) => {
                // 带文件输出的配置
                let file = self.open_log_file(file_path)?;
                
                match self.config.format.as_str() {
                    "json" => {
                        Registry::default()
                            .with(env_filter)
                            .with(fmt::layer().json().with_writer(std::io::stderr))
                            .with(fmt::layer().json().with_writer(file).with_ansi(false))
                            .init();
                    }
                    "text" => {
                        Registry::default()
                            .with(env_filter)
                            .with(fmt::layer().compact().with_writer(std::io::stderr))
                            .with(fmt::layer().json().with_writer(file).with_ansi(false))
                            .init();
                    }
                    _ => {
                        return Err(Error::InvalidConfig(format!("Unsupported log format: {}", self.config.format)));
                    }
                }
            }
            None => {
                // 仅控制台输出
                match self.config.format.as_str() {
                    "json" => {
                        Registry::default()
                            .with(env_filter)
                            .with(fmt::layer().json())
                            .init();
                    }
                    "text" => {
                        Registry::default()
                            .with(env_filter)
                            .with(fmt::layer().compact())
                            .init();
                    }
                    "pretty" => {
                        Registry::default()
                            .with(env_filter)
                            .with(fmt::layer().pretty())
                            .init();
                    }
                    _ => {
                        return Err(Error::InvalidConfig(format!("Unsupported log format: {}", self.config.format)));
                    }
                }
            }
        }
        
        tracing::info!(
            "Logging system initialized - level: {}, format: {}", 
            self.config.level, 
            self.config.format
        );
        
        Ok(())
    }
    
    /// 创建环境过滤器
    fn create_env_filter(&self) -> Result<EnvFilter> {
        let level = self.parse_log_level(&self.config.level)?;
        
        let filter = EnvFilter::builder()
            .with_default_directive(level.into())
            .from_env()
            .map_err(|e| Error::internal(format!("Failed to create env filter: {}", e)))?
            .add_directive("hyper=warn".parse().unwrap())
            .add_directive("reqwest=warn".parse().unwrap())
            .add_directive("h2=warn".parse().unwrap())
            .add_directive("tower=warn".parse().unwrap());
            
        Ok(filter)
    }
    
    /// 打开日志文件
    fn open_log_file(&self, file_path: &PathBuf) -> Result<std::fs::File> {
        // 确保目录存在
        if let Some(parent) = file_path.parent() {
            std::fs::create_dir_all(parent)
                .map_err(|e| Error::internal(format!("Failed to create log directory: {}", e)))?;
        }
        
        // 打开日志文件（追加模式）
        OpenOptions::new()
            .create(true)
            .append(true)
            .open(file_path)
            .map_err(|e| Error::internal(format!("Failed to open log file: {}", e)))
    }
    
    /// 解析日志级别字符串
    fn parse_log_level(&self, level_str: &str) -> Result<Level> {
        match level_str.to_lowercase().as_str() {
            "trace" => Ok(Level::TRACE),
            "debug" => Ok(Level::DEBUG),
            "info" => Ok(Level::INFO),
            "warn" => Ok(Level::WARN),
            "error" => Ok(Level::ERROR),
            _ => Err(Error::InvalidConfig(format!("Invalid log level: {}", level_str)))
        }
    }
    
    /// 创建结构化日志事件
    pub fn log_sandbox_event(&self, event_type: &str, sandbox_id: &str, details: serde_json::Value) {
        tracing::info!(
            event_type = event_type,
            sandbox_id = sandbox_id,
            details = %details,
            "Sandbox event occurred"
        );
    }
    
    /// 记录性能指标
    pub fn log_performance_metric(&self, metric_name: &str, value: f64, labels: Option<serde_json::Value>) {
        tracing::info!(
            metric_name = metric_name,
            value = value,
            labels = ?labels,
            "Performance metric"
        );
    }
    
    /// 记录安全事件
    pub fn log_security_event(&self, event_type: &str, severity: &str, description: &str, context: Option<serde_json::Value>) {
        tracing::warn!(
            event_type = event_type,
            severity = severity,
            description = description,
            context = ?context,
            "Security event detected"
        );
    }
    
    /// 记录错误事件
    pub fn log_error_event(&self, error: &crate::Error, context: Option<serde_json::Value>) {
        tracing::error!(
            error_code = error.error_code(),
            error_message = %error,
            error_retryable = error.is_retryable(),
            context = ?context,
            "Error occurred"
        );
    }
}

/// 日志装饰器trait
/// 
/// 为其他结构提供统一的日志记录能力
pub trait LoggingDecorator {
    /// 获取组件名称
    fn component_name(&self) -> &'static str;
    
    /// 记录信息日志
    fn log_info(&self, message: &str, context: Option<serde_json::Value>) {
        tracing::info!(
            component = self.component_name(),
            message = message,
            context = ?context,
            "Component info"
        );
    }
    
    /// 记录警告日志
    fn log_warn(&self, message: &str, context: Option<serde_json::Value>) {
        tracing::warn!(
            component = self.component_name(),
            message = message,
            context = ?context,
            "Component warning"
        );
    }
    
    /// 记录错误日志
    fn log_error(&self, error: &crate::Error, context: Option<serde_json::Value>) {
        tracing::error!(
            component = self.component_name(),
            error_code = error.error_code(),
            error_message = %error,
            error_retryable = error.is_retryable(),
            context = ?context,
            "Component error"
        );
    }
    
    /// 记录性能指标
    fn log_metric(&self, metric_name: &str, value: f64, labels: Option<serde_json::Value>) {
        tracing::info!(
            component = self.component_name(),
            metric_name = metric_name,
            value = value,
            labels = ?labels,
            "Component metric"
        );
    }
}

/// 日志上下文构建器
/// 
/// 用于构建结构化日志的上下文信息
#[derive(Debug, Default)]
pub struct LogContext {
    fields: serde_json::Map<String, serde_json::Value>,
}

impl LogContext {
    /// 创建新的日志上下文
    pub fn new() -> Self {
        Self::default()
    }
    
    /// 添加字符串字段
    pub fn with_str(mut self, key: &str, value: &str) -> Self {
        self.fields.insert(key.to_string(), serde_json::Value::String(value.to_string()));
        self
    }
    
    /// 添加数字字段
    pub fn with_number<T: Into<serde_json::Number>>(mut self, key: &str, value: T) -> Self {
        self.fields.insert(key.to_string(), serde_json::Value::Number(value.into()));
        self
    }
    
    /// 添加布尔字段
    pub fn with_bool(mut self, key: &str, value: bool) -> Self {
        self.fields.insert(key.to_string(), serde_json::Value::Bool(value));
        self
    }
    
    /// 添加JSON值字段
    pub fn with_json(mut self, key: &str, value: serde_json::Value) -> Self {
        self.fields.insert(key.to_string(), value);
        self
    }
    
    /// 转换为JSON值
    pub fn to_json(self) -> serde_json::Value {
        serde_json::Value::Object(self.fields)
    }
}


#[cfg(test)]
mod tests {
    use super::*;
    use tempfile::tempdir;
    
    #[test]
    fn test_logging_manager_creation() {
        let config = LoggingConfig {
            level: "info".to_string(),
            format: "json".to_string(),
            file_path: None,
            max_file_size_mb: 100,
            max_files: 5,
        };
        
        let manager = LoggingManager::new(config);
        assert_eq!(manager.config.level, "info");
        assert_eq!(manager.config.format, "json");
    }
    
    #[test]
    fn test_log_level_parsing() {
        let config = LoggingConfig::default();
        let manager = LoggingManager::new(config);
        
        assert!(matches!(manager.parse_log_level("info"), Ok(Level::INFO)));
        assert!(matches!(manager.parse_log_level("debug"), Ok(Level::DEBUG)));
        assert!(matches!(manager.parse_log_level("error"), Ok(Level::ERROR)));
        assert!(manager.parse_log_level("invalid").is_err());
    }
    
    #[test]
    fn test_log_context_builder() {
        let context = LogContext::new()
            .with_str("operation", "sandbox_create")
            .with_number("duration_ms", 150)
            .with_bool("success", true);
        
        let json = context.to_json();
        assert!(json.is_object());
        
        let obj = json.as_object().unwrap();
        assert_eq!(obj.get("operation").unwrap().as_str().unwrap(), "sandbox_create");
        assert_eq!(obj.get("duration_ms").unwrap().as_i64().unwrap(), 150);
        assert_eq!(obj.get("success").unwrap().as_bool().unwrap(), true);
    }
    
    #[test]
    fn test_env_filter_creation() {
        let config = LoggingConfig {
            level: "debug".to_string(),
            format: "json".to_string(),
            file_path: None,
            max_file_size_mb: 100,
            max_files: 5,
        };
        
        let manager = LoggingManager::new(config);
        let filter_result = manager.create_env_filter();
        assert!(filter_result.is_ok());
    }
    
    struct TestComponent;
    
    impl LoggingDecorator for TestComponent {
        fn component_name(&self) -> &'static str {
            "test_component"
        }
    }
    
    #[test]
    fn test_logging_decorator() {
        let component = TestComponent;
        assert_eq!(component.component_name(), "test_component");
        
        // 这些方法会输出日志，但在测试中我们只验证它们不会panic
        component.log_info("test message", None);
        component.log_warn("warning message", None);
        component.log_metric("test_metric", 42.0, None);
    }
}